package com.gyl.aspect;

import com.gyl.aspect.annotation.WebMethodVerify;
import com.gyl.aspect.beanverify.BeanVerify;
import com.gyl.aspect.utils.LogFormatUtil;
import com.gyl.aspect.utils.ServletUtil;
import com.gyl.common.utils.StringUtil;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Import;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Optional;

import cn.hutool.core.date.DateUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * web请求切面类
 *
 * @author gyl
 * @date 2022/5/10 - 14:51
 */
@Component
@Slf4j
@Aspect
@Import(BeanVerify.class)
public class WebAspect {

    @Autowired
    BeanVerify beanVerify;

    /**
     * 切入点
     */
    @Pointcut("@annotation(com.gyl.aspect.annotation.WebMethodVerify)")
    public void excuteMethod() {
    }

    /**
     * 环形切入
     */
    @Around("excuteMethod()")
    public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        // 获取请求uri
        String requestURI = ServletUtil.getRequest().getRequestURI();
        // 获取请求方法
        MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature();
        // 获取注解value值
        Method method = methodSignature.getMethod();
        WebMethodVerify annotation = method.getAnnotation(WebMethodVerify.class);
        String methodName = null == annotation ? "" : annotation.value();
        Object[] args = proceedingJoinPoint.getArgs();
        String requestId = String.valueOf(DateUtil.current());
        // 请求打印
        log.info(LogFormatUtil.beforeHandle(methodName, requestURI, args, requestId));
        // 校验入参
        Object result = null;

        if (null != annotation) {
            for (Object object : args) {
                object = Optional.ofNullable(object).orElse(new Object());
                long start = System.currentTimeMillis();
                log.info(StringUtil.append("请求参数【", object.getClass().getName(), "】合法性校验开始"));
                beanVerify.Verify(object);
                long time = System.currentTimeMillis() - start;
                log.info(StringUtil.append("请求参数【", object.getClass().getName(), "】合法性校验通过，耗时【", String.valueOf(time), "】ms！"));
            }
        }
        // 执行方法
        long begin = System.currentTimeMillis();
        result = proceedingJoinPoint.proceed(args);
        long totalTime = System.currentTimeMillis() - begin;
        log.info(LogFormatUtil.handleSucceed(methodName, totalTime, result, requestId));

        return result;
    }
}
